package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.api.feign.ApArticleFeignClient;
import com.heima.audit.baidu.BaiduImageScan;
import com.heima.audit.baidu.BaiduTextScan;
import com.heima.file.service.FileStorageService;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.pojos.WmChannel;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.wemedia.mapper.WmChannelMapper;
import com.heima.wemedia.service.WmNewsAuditService;
import com.heima.wemedia.service.WmNewsService;
import com.heima.wemedia.service.WmSensitiveService;
import com.heima.wemedia.service.WmUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
public class WmNewsAuditServiceImpl implements WmNewsAuditService {


    @Autowired
    private ApArticleFeignClient articleFeignClient;

    @Autowired
    private WmUserService wmUserService;

    @Autowired
    private WmChannelMapper wmChannelMapper;

    @Autowired
    private WmNewsService wmNewsService;

    /**
     * 文章自动审核
     * @param wmNews
     * @param contentImageList
     * @return
     */
    @Async("taskExecutor")
    @Override
    public void auditWmNews(WmNews wmNews, List<String> contentImageList) {

        try {
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //1. 准备待审核的数据（文本和图片）
        //1.1 准备所有文本（标题、标签、内容文本）
        String allText = this.prepareAllText(wmNews);

        //1.2 准备所有图片地址（封面图片、内容图片，去重）
        List<String> allImage = this.prepareAllImage(wmNews, contentImageList);

        //2. 百度云文本审核
        ResponseResult responseResult = this.baiduTextScan(wmNews, allText);
        if(responseResult!=null){
            log.error("[文章自动审核]百度云文本审核出现问题（可能不合规或疑似），文章ID：{}",wmNews.getId());
            return ;
        }

        //3. 百度云图片审核
        responseResult = this.baiduImageScan(wmNews, allImage);
        if(responseResult!=null){
            log.error("[文章自动审核]百度云图片审核出现问题（可能不合规或疑似），文章ID：{}",wmNews.getId());
            return ;
        }

        //4. 处理APP文章的发布
        //4.1 获取系统当前时间和文章发布时间
        long currentTime = DateTime.now().getMillis();
        long publishTime = wmNews.getPublishTime().getTime();

        //4.2 发布时间未到，则修改文章状态为自动审核通过（待发布8）
        if(publishTime>currentTime){
            this.updateWmNews(wmNews,WmNews.Status.SUCCESS.getCode(),"文章审核通过，发布时间未到");
            log.info("[文章自动审核]文章审核通过待发布，文章ID：{}",wmNews.getId());
            return ;
        }

        //4.3 发布时间用到，则 调用Feign创建或更新APP文章  且 修改文章状态为已发布（9）
        responseResult = this.doArticlePublish(wmNews);
        if(responseResult!=null){
            log.error("[文章自动审核]处理APP文章发布出现问题，文章ID：{}",wmNews.getId());
            return;
        }

        log.info("[文章自动审核]文章审核通过已发布，文章ID：{}",wmNews.getId());
    }

    @Autowired
    private WmSensitiveService wmSensitiveService;


    /**
     * 更新文章
     * @param wmNews
     * @param status
     * @param reason
     */
    private void updateWmNews(WmNews wmNews,Short status,String reason){
        wmNews.setReason(reason);
        wmNews.setStatus(status);
        wmNewsService.updateById(wmNews);
    }

    /**
     * 发布时间用到，则 调用Feign创建或更新APP文章  且 修改文章状态为已发布（9）
     * @param wmNews
     * @return
     */
    public ResponseResult doArticlePublish(WmNews wmNews){
        //4.3.1 调用Feign创建或更新APP文章
        ArticleDto dto = new ArticleDto();
        dto.setId(wmNews.getArticleId());
        dto.setTitle(wmNews.getTitle());
        dto.setChannelId(wmNews.getChannelId());
        dto.setLayout(wmNews.getType());
        dto.setImages(wmNews.getImages());
        dto.setLabels(wmNews.getLabels());
        dto.setPublishTime(wmNews.getPublishTime());
        dto.setContent(wmNews.getContent());
        //查询自媒体用户
        WmUser wmUser = wmUserService.getById(wmNews.getUserId());
        if(wmUser!=null){
            dto.setAuthorId(wmUser.getApAuthorId().longValue());//作者id
            dto.setAuthorName(wmUser.getName());//作者名
        }

        //查询频道
        WmChannel wmChannel = wmChannelMapper.selectById(wmNews.getChannelId());
        if(wmChannel!=null){
            dto.setChannelName(wmChannel.getName());//频道名
        }

        //行为数据默认值
        dto.setLikes(0);
        dto.setCollection(0);
        dto.setComment(0);
        dto.setViews(0);

        if(dto.getId()==null){
            dto.setCreatedTime(new Date());//创建时间
        }

        ResponseResult responseResult = articleFeignClient.save(dto);
        if(responseResult.getCode()!=200){
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR, "调用Feign失败");
        }

        long articleId = Long.valueOf(String.valueOf(responseResult.getData()));

        //4.3.2 修改文章状态为已发布（9）
        wmNews.setArticleId(articleId);
        this.updateWmNews(wmNews,WmNews.Status.PUBLISHED.getCode(),"审核通过已发布");

        return null;
    }

    @Autowired
    private BaiduImageScan baiduImageScan;

    @Autowired
    private FileStorageService fileStorageService;

    /**
     * 百度云图片审核
     * @param wmNews
     * @param allImage
     * @return
     */
    private ResponseResult baiduImageScan(WmNews wmNews, List<String> allImage) {
        if(allImage.size()>0){
            for (String url : allImage) {
                //下载图片的字节数组
                byte[] bytes = fileStorageService.downLoadFile(url);

                Integer imageType = baiduImageScan.imageScan(bytes);

                //如果审核不合规，则更新文章状态为审核失败（2）
                if(imageType==2){
                    this.updateWmNews(wmNews,WmNews.Status.FAIL.getCode(),"百度云图片审核不合规");

                    return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"百度云图片审核不合规");
                } else if(imageType==3){
                    this.updateWmNews(wmNews,WmNews.Status.ADMIN_AUTH.getCode(),"百度云图片审核疑似");

                    return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"百度云图片审核疑似");
                }
            }
        }
        return null;
    }


    @Autowired
    private BaiduTextScan baiduTextScan;
    /**
     * 百度云文本审核
     * @param wmNews
     * @param allText
     * @return
     */
    private ResponseResult baiduTextScan(WmNews wmNews,String allText){
        Integer textType = baiduTextScan.textScan(allText);
        //如果审核不合规，则更新文章状态为审核失败（2）
        if(textType==2){
            this.updateWmNews(wmNews,WmNews.Status.FAIL.getCode(),"百度云文本审核不合规");

            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"百度云文本审核不合规");
        } else if(textType==3){
            //如果审核疑似，则更细文章状态为待人工审核（3）
            this.updateWmNews(wmNews,WmNews.Status.ADMIN_AUTH.getCode(),"百度云文本审核疑似");

            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"百度云文本审核疑似");
        }
        return null;
    }

    /**
     * 准备所有图片地址（封面图片、内容图片，去重）
     * @param wmNews
     * @param contentImageList
     * @return
     */
    private static List<String> prepareAllImage(WmNews wmNews, List<String> contentImageList) {
        if(StringUtils.isNotBlank(wmNews.getImages())){
            String[] coverImageArr = wmNews.getImages().split(",");
            List<String> coverImageList = Arrays.asList(coverImageArr); //封面图片地址
            contentImageList.addAll(coverImageList);
        }
        List<String> allImage = contentImageList.stream().distinct().collect(Collectors.toList());
        return allImage;
    }

    /**
     * 准备所有文本（标题、标签、内容文本）
     * @param wmNews
     * @return
     */
    private static String prepareAllText(WmNews wmNews) {
        StringBuffer allTextBuffer = new StringBuffer();
        allTextBuffer.append(wmNews.getTitle());//标题
        allTextBuffer.append(wmNews.getLabels());//标签
        List<Map> contentMapList = JSON.parseArray(wmNews.getContent(), Map.class);
        for (Map<String,String> contentMap : contentMapList) {
            String type = contentMap.get("type");
            if("text".equals(type)){
                String contentText = contentMap.get("value");//内容文本
                allTextBuffer.append(contentText);
            }
        }
        String allText = allTextBuffer.toString();//所有待审核的文本
        return allText;
    }
}